# -*- coding: utf-8 -*-

# 内部包应用
from typing import List, Optional

# 自定义包应用
from dtcloud.http import request, _logger

from commons.exceptions.errors import ValidationError
from commons.Fields.BaseConvert import converts

DATASCOPE_CHOICES = (
    (1, "全部数据权限"),
    (2, "仅本人数据权限")
)


class CRUDBase:
    """
    基础类ORM
    """
    _model: str = None
    _order: str = "id desc"
    _fields: Optional[List[str]] = None
    _domains: Optional[List[List[str]]] = None
    _offset_fields = ['create_uid', 'write_uid', '__last_update', 'display_name']

    @classmethod
    def home_public_list(cls, domains=None, field_list=None, model=None, **kwargs):
        """
        列表详情读取
        """
        field_list = field_list or cls._fields
        domains = domains or cls._domains  # 额外的搜索条件，列表形式
        model = model or cls._model

        page = int(kwargs.get("page", 1))
        limit = int(kwargs.get("limit") or kwargs.get("pageSize") or 20)
        offset = (page - 1) * limit

        domain = cls.home_public_domain(domains, model, **kwargs)
        _logger.info(f"domain: {domain}")
        pool = request.env
        order = kwargs.get('order') or cls._order
        records = pool[model].with_user(request.uid).sudo().search(
            domain, limit=limit, offset=offset, order=order)
        count = pool[model].with_user(request.uid).sudo().search_count(domain)
        if count != 0:
            record_list = cls.home_public_read(records, field_list)
            return record_list, count
        return [], 0

    @classmethod
    def home_public_domain(cls, domains: list = None, model: str = None, **kwargs) -> list:
        """
        列表详情搜索 未能解决传入的domain和kwargs的中存在相同的key的情况
        :param model: 需要搜索的模型
        :param kwargs: 搜索参数：通常为前端传递的参数，字典形式
        :param domains: 额外的搜索条件，列表形式
        :param kwargs: 其他参数,字典形式,当字段需要支持模糊搜索时，传入的参数为字典形式，如：{'name': {'$regex': 'test'}}
        """
        offset = ['limit', 'page', 'order']
        fields = request.env[model].with_user(request.uid).sudo()._fields
        domain = []
        if domains and isinstance(domains, list):
            domain.extend(domains)

        # 过滤掉不在fields中的字段
        valid_kwargs = filter(lambda kv: kv[0] in fields and kv[0] not in offset, kwargs.items())
        # 将参数转换为domain map
        domain_extensions = map(lambda kv: converts[fields[kv[0]].type].to_domain(fields[kv[0]], kv[1]), valid_kwargs)
        # 将domain map转换为domain list
        flat_domain_extensions = [item for sublist in domain_extensions for item in sublist]
        domain.extend(flat_domain_extensions)
        return domain

    @classmethod
    def home_public_read(cls, records, field_list) -> list:
        """
        读取列表数据部件之一，返回对应数据集合，自动编码序号 RecordNumber
        :param records: 数据集合
        :param field_list: 需要读取的字段列表
        """

        fields = records._fields
        field_list = field_list or list(records._fields)
        field_list = list(filter(lambda ele: ele not in cls._offset_fields, field_list))

        # records_list = []
        active = fields.get('active', False)
        if active:
            records = records.filtered(lambda x: x.active and x.active == True)
        # for rec in records:
        #     field_read = {}
        #     for field in field_list:
        #         field_ins = fields[field]
        #         if field_ins.type in converts:
        #             field_read[field] = converts[field_ins.type].to_read(rec, field_ins)
        #         else:
        #             field_read[field] = field_ins.convert_to_read(rec[field], rec)
        #     records_list.append(field_read)

        records_list = [
            {
                field: (converts[fields[field].type].to_read(rec, fields[field])
                        if fields[field].type in converts
                        else fields[field].convert_to_read(rec[field], rec))
                for field in field_list
            }
            for rec in records
        ]
        return records_list

    @classmethod
    def home_public_create_dict(cls, data, model: str = None) -> bool:
        """
        返回正确的创建数据集合，易扩展
        :param model: 模型
        :param data: 数据集合
        """
        model = model or cls._model
        fields = request.env[model].with_user(request.uid).sudo().fields_get()
        # keys = []
        # for rec in data:
        #     # 空值 字段不存在
        #     if not data[rec] or rec not in fields.keys():
        #         keys.append(rec)
        #         continue
        #     data[rec] = converts[fields[rec]['type']].to_field(data[rec])
        # for k in keys:
        #     del data[k]

        keys_to_remove = [rec for rec in data if not data[rec] or rec not in fields.keys()]
        data = {rec: (converts[fields[rec]['type']].to_field(data[rec], metadata=fields[rec])
                      if fields[rec]['type'] in ['one2many', 'many2many']
                      else converts[fields[rec]['type']].to_field(data[rec]))
                for rec in data if rec not in keys_to_remove}

        for key in keys_to_remove:
            data.pop(key, None)

        if not data:
            return False
        try:
            model_res = request.env[model].sudo().create(data)
            if model_res.id:
                return True
            else:
                return False
        except Exception as e:
            _logger.warning("创建失败", e)
            return False

    @classmethod
    def home_public_write_dict(cls, data, model: str = None) -> bool:
        """
        获取正确的更新数据集合，不直接更新，易扩展
        """
        model = model or cls._model
        fields = request.env[model].with_user(request.uid).sudo().fields_get()
        keys = []
        for rec in data:
            # 空值 / 不存在
            if not data[rec] or rec not in fields.keys():
                keys.append(rec)
                continue

            if fields[rec]['type'] in ['one2many', 'many2many']:
                data[rec] = converts[fields[rec]['type']].to_field(data[rec], update=True)
            else:
                data[rec] = converts[fields[rec]['type']].to_field(data[rec])
        # for k in keys:
        #     # 删除为空的Key
        #     if fields[k]['type'] in ['many2one', 'one2many', 'many2many']:
        #         del data[k]

        record = request.env[model].sudo().browse(int(data["id"]))
        del data['id']
        try:
            model_res = record.write(data)
            if model_res:
                return True
            else:
                return False
        except Exception as e:
            _logger.warning("更新失败", e)
            return False

    @classmethod
    def home_public_unlink(cls, model, vals):
        """
        归档数据，使其不可见，失灵添加 active = fields.Boolean() 字段生效
        """
        try:
            # 是否强制删除
            is_force_delete = vals.get("is_force_delete", False)
            # 该模型下是否有关联
            is_unlink = 1
            Model = request.env[model].with_user(request.uid).sudo().browse(int(vals.get("id")))
            fields = Model.fields_get()
            for field_name, field_property in fields.items():
                # 字段类型
                field_type = field_property.get('type')
                if field_type in ['one2many', 'many2many'] and Model[field_name]:
                    is_unlink = 0
            if is_unlink == 1 or is_force_delete:
                Model.toggle_active()
                return 1
            if is_unlink == 0:
                return -1

        except Exception as r:
            _logger.warning("删除失败", r)
            return 0

    @classmethod
    def home_public_unlink_true(cls, model, id):
        """
        真删除数据
        """
        try:
            request.env[model].with_user(request.uid).sudo().browse(int(id)).unlink()
            return '删除成功！'
        except Exception as r:
            return '错误: %s' % r

    @classmethod
    def home_public_read_one(cls, id: int, field_list):
        """
        获取单据详情数据，返回字典集合
        """
        # 如果传了field_list，就用传的，否则用类的
        field_list = field_list or cls._fields
        res = request.env[cls._model].with_user(request.uid).sudo().browse(int(id))
        record = cls.home_public_read(res, field_list)[0]
        return record

    @classmethod
    def home_public_check_params(cls, model, vals):
        """
        检查vals参数的key是否在model中存在
        后续建议直接使用pydantic模型校验
        """
        fields = request.env[model].with_user(request.uid).sudo().fields_get()
        for rec in vals:
            if rec not in fields.keys():
                raise ValidationError(400, f"参数错误，{rec}不在{model}中存在！")
        return True

    @classmethod
    def home_public_delete(cls, rids, model=None):
        """id单个删除、批量删除"""
        model = model or cls._model
        return request.env[model].sudo().browse(rids).unlink()

    @classmethod
    def update_by_id(cls, model: str, id: int, **kwargs):
        """
        更新数据
        :param model: 模型
        :param id: id
        :param kwargs: 更新的字段
        """
        return request.env[model].sudo().browse(id).write(kwargs)
